#ifndef __LIB_KERNEL_LIST_H
#define __LIB_KERNEL_LIST_H
#include "global.h"

/**********   定义链表结点成员结构   ***********
*结点中不需要数据成元,只要求前驱和后继结点指针*/
struct list_elem {
   struct list_elem* prev; // 前躯结点
   struct list_elem* next; // 后继结点
};

/* 链表结构,用来管理整个队列 */
struct list {
/* head是队首,是固定不变的，不是第1个元素,第1个元素为head.next */
   struct list_elem head;
/* tail是队尾,同样是固定不变的 */
   struct list_elem tail;
};

//定义个叫function的函数类型，返回值是int，参数是链表结点指针与一个整形值
typedef bool (function)(struct list_elem*, int arg);

//用于计算一个结构体成员在结构体中的偏移量
#define offset(struct_type,member_name) (int)(&(((struct_type*)0)->member_name))
//用于通过一个结构体成员地址计算出整个结构体的起始地址
#define member_to_entry(struct_type,member_name,member_ptr) (struct_type*)((int)member_ptr-offset(struct_type,member_name))

/* 初始化双向链表list */
void list_init(struct list* list);

/* 把链表元素elem插入在元素before之前 */
void list_insert_before(struct list_elem* before, struct list_elem* elem);


/* 添加元素到列表队首,类似栈push操作，添加结点到链表队首，类似于push操作, 参数1是链表的管理结点，参数2是一个新结点 */
void list_push(struct list* plist, struct list_elem* elem) ;

/* 追加元素到链表队尾,类似队列的先进先出操作，添加结点到队尾，实际上就是添加结点到管理结点之前。参数是管理结点与要添加的结点 */
void list_append(struct list* plist, struct list_elem* elem) ;

/* 使元素pelem脱离链表 */
void list_remove(struct list_elem* pelem) ;

/* 将链表第一个元素弹出并返回,类似栈的pop操作，参数是链表的管理结点（入口结点） */
struct list_elem* list_pop(struct list* plist) ;

/* 从链表中查找元素obj_elem,成功时返回true,失败时返回false */
bool elem_find(struct list* plist, struct list_elem* obj_elem) ;

/* 判断链表是否为空,空时返回true,否则返回false */
int list_empty(struct list* list);

/* 返回链表长度，不包含管理结点，参数就是链表的管理结点 */
uint32_t list_len(struct list* list);

/* 把列表plist中的每个元素elem和arg传给回调函数func,
 * arg给func用来判断elem是否符合条件.
 * 本函数的功能是遍历列表内所有元素,逐个判断是否有符合条件的元素。
 * 找到符合条件的元素返回元素指针,否则返回NULL. */
struct list_elem* list_traversal(struct list* plist, function func, int arg) ;


#endif

